// Copyright (C) 2005-2008 Jae Stutzman (jaebird@gmail.com)
//
// This file is part of SoundConsole.
//
// SoundConsole is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// SoundConsole is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SoundConsole.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.IO;
using System.Runtime.InteropServices;

namespace SoundConsole
{
	class Program
	{
		private short bits;
		private short channels;
		private int rate;
		private TimeSpan duration;
		private int deviceIndex;
		private ConsoleCtrl cc = new ConsoleCtrl();

		private SoundCapture soundCapture = null;

		// The main entry point for the application.
		static void Main(string[] args)
		{
			try
			{
				Program main = new Program(args);

				// app hangs here until exit
				main.Run();

				System.Environment.Exit(-1);

			}
			catch(Exception e)
			{
				Console.Error.WriteLine(e);
			}
		}

		public Program(string[] args)
		{
			cc.ControlEvent += new ConsoleCtrl.ControlEventHandler(InputHandler);

			if (args.Length == 0)
			{
				PrintOutput();
				throw new Exception("No Args");
			}
			else
			{
				ParseCommandLine(args);
				soundCapture = new SoundCapture(bits, channels, rate, duration, deviceIndex);
			}
		}

		public void Run()
		{
			string stopFile = Environment.CurrentDirectory + @"\sndconsole.stop.flag";
			string pauseFile = Environment.CurrentDirectory + @"\sndconsole.pause.flag";

			soundCapture.Start();

			while (true)
			{
				System.Threading.Thread.Sleep(1000);
				
				//Console.Error.WriteLine(stopFile + " exists? " + File.Exists(stopFile).ToString());

				if (File.Exists(stopFile))
				{
					soundCapture.Stop();
					return;
				}
				else
				{
					bool paused = File.Exists(pauseFile);

					if (paused && soundCapture.Capturing)
					{
						soundCapture.Stop();
					}
					else if (!paused && !soundCapture.Capturing)
					{
						soundCapture.Start();
					}
				}

			}
		}

		void ParseCommandLine(string[] args)
		{
			for (int i = 0; i < args.Length; i++)
			{
//				if (args[i].StartsWith("-"))
//				{
					switch (args[i])
					{
						case "-B" :
						case "--bits" :
						{
							i++;
							bits = System.Convert.ToInt16(args[i], 10);
						}
						break;

						case "-C" :
						case "--channels" :
						{
							i++;
							channels = System.Convert.ToInt16(args[i], 10);
						}
						break;

						case "-R" :
						case "--rate" :
						{
							i++;
							rate = System.Convert.ToInt32(args[i], 10);
						}
						break;

						case "-D" :
						case "--duration" :
						{
							i++;
							duration = TimeSpan.Parse(args[i]);
						}
						break;

						case "-dev" :
						case "--device" :
						{
							i++;
							deviceIndex = System.Convert.ToInt32(args[i], 10);
						}
						break;

						case "-lsdev" :
						{
							SoundCapture cap = new SoundCapture();
							string [] devices = cap.GetCaptureDevices();

							Console.WriteLine("Sound Capture Devices:");
							foreach (string device in devices)
							{
								Console.WriteLine(device);
							}
							return;
						}
						default :
						{
							PrintOutput();
							return;
						}
					}
//				}
//				else
//				{
//				}
			}
		}

		static void PrintOutput()
		{
			Console.WriteLine("sndconsole v0.01 (2006-04-20)");
			Console.WriteLine("Copyright (C) 2006-2008 Jae Stutzman");
			Console.WriteLine();
			Console.WriteLine("This program comes with ABSOLUTELY NO WARRANTY.");
			Console.WriteLine("This is free software, and you are welcome to redistribute it");
			Console.WriteLine("under certain conditions; See the file LICENSE.txt for details.");
			Console.WriteLine();
			Console.WriteLine("DESCRIPTION:");
			Console.WriteLine("This program allows to encode live audio with any audio coder which accepts");
			Console.WriteLine("raw PCM data on STDIN. Tested with OGG Vorbis, LAME, FLAC and Speex.");
			Console.WriteLine();
			Console.WriteLine("USAGE:");
			Console.WriteLine("sndconsole <options> | <encoder> <options>");
			Console.WriteLine();
			Console.WriteLine("OPTIONS:");
			Console.WriteLine("-B, --bits       Set number of bits per sample.");
			Console.WriteLine("-C, --channels   Set number of channels.");
			Console.WriteLine("-R, --rate       Set number of samples per second(sample rate).");
			Console.WriteLine("-D, --duration   Specify maximum record duration(h:m:s).");
			Console.WriteLine("-dev, --device   Specify the sound device to be used for recording.");
			Console.WriteLine("-lsdev           List the installed sound devices and exit.");
//			Console.WriteLine("-ff              Support \"flag-files\".");
			Console.WriteLine();
			Console.WriteLine("EXAMPLES:");
			Console.WriteLine("sndconsole -B 16 -C 1 -R 44100 | oggenc -r -B 16 -C 1 -R 44100 -q 1 - -o out.ogg");
			Console.WriteLine("sndconsole -B 16 -C 2 -R 44100 | lame -r -x -s 44.1 --bitwidth 16 --r3mix - out.mp3");
			Console.WriteLine("HINTS:");
			Console.WriteLine("* Make sure you specify the same bits/channels/rate parameters to sndconsole");
			Console.WriteLine("AND to the encoder.");
			Console.WriteLine("* After the recording starts, you may terminate it by pressing \"Ctrl-C\",");
			Console.WriteLine("or by killing \"sndconsole.exe\" from the Task Manager.");
		}

		public void InputHandler(ConsoleCtrl.ConsoleEvent consoleEvent)
		{
			if (consoleEvent == ConsoleCtrl.ConsoleEvent.CtrlC)
			{
				// Cleanup code here.
				soundCapture.Dispose();

				System.Environment.Exit(-1);
			}
		}

	}
}
